package com.shen.jcbf.jdk8bf.lambda;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileFilter;
import java.util.*;

import javax.swing.JButton;

import org.apache.poi.util.StringUtil;
import org.junit.Test;

/**
 * 说明：测试jdk8新特性之二：Lambda 表达式，集合排序。
 * 
 * @author shenhx
 * @date 2017年5月20日
 */
public class TestCollection {

	/**
	 * 说明：
	 * 
	 * @author shenhx
	 * @date 2017年5月20日
	 */
	@Test
	public void Test001() {
		List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");

		// 原方式
		Collections.sort(names, new Comparator<String>() {
			@Override
			public int compare(String a, String b) {
				return b.compareTo(a);
			}
		});

		// jdk8 方式
		Collections.sort(names, (String a, String b) -> {
			return b.compareTo(a);
		});

		// jdk8 方式,简略一次
		Collections.sort(names, (String a, String b) -> b.compareTo(a));

		// jdk8 方式,简略二次
		Collections.sort(names, (a, b) -> b.compareTo(a));

		System.out.println(names);
	}

	@Test
	public void test002() {
		FileFilter java = (File f) -> f.getName().endsWith("*.java");
		System.out.println(java);
		
		//********************************************************

		// Java 8之前：
		new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("Before Java8, too much code for too little to do");
			}
		}).start();

		// Java 8方式：
		new Thread(() -> System.out.println("In Java8, Lambda expression rocks !!")).start();

		//********************************************************
		
		// Java 8之前：
		JButton show = new JButton("Show");
		show.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				System.out.println("Event handling without lambda expression is boring");
			}
		});
		// Java 8方式：
		show.addActionListener((e) -> {
			System.out.println("Light, Camera, Action !! Lambda expressions Rocks");
		});

		//********************************************************
		
		// Java 8之后：
		List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
		features.forEach(n -> System.out.println(n));
		 
		// 使用Java 8的方法引用更方便，方法引用由::双冒号操作符标示，
		// 看起来像C++的作用域解析运算符
		features.forEach(System.out::println);
	}

	/**
	 * 测试 lambda 表达式的接口的测试
	 *
	 * 需要注意如果@FunctionalInterface如果没有指定，代码也是对的。

	 译者注 将lambda表达式映射到一个单方法的接口上，这种做法在Java 8之前就有别的语言实现，比如Rhino JavaScript解释器，
	 如果一个函数参数接收一个单方法的接口而你传递的是一个function，Rhino 解释器会自动做一个单接口的实例到function的适配器，
	 典型的应用场景有 org.w3c.dom.events.EventTarget 的addEventListener 第二个参数 EventListener。
	 *
	 */
	public void testJK(){

		Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
		Integer converted = converter.convert("123");
		System.out.println(converted);    // 123

	}

	/**
	 * 代码还可以通过静态方法引用来表示：
	 */
	public void testJK2(){

		//Java 8 允许你使用 :: 关键字来传递方法或者构造函数引用，这里展示了如何引用一个静态方法
		Converter<String, Integer> converter = Integer::valueOf;
		Integer converted = converter.convert("123");
		System.out.println(converted);   // 123

	}

	/**
	 * Java 8 允许你使用 :: 关键字来传递方法或者构造函数引用，上面的代码展示了如何引用一个静态方法，我们也可以引用一个对象的方法：
	 */
	@Test
	public void testJK3(){

		//我们也可以引用一个对象的方法
		/*Converter converter = somehting::startsWith;
		String converted = converter.convert("Java");
		System.out.println(converted);    // "J"*/

	}

	@Test
	public void testmaohao(){

		Person p = new Person("fdjafdajlfk");
		Runnable getName = p::getName;
		System.out.println(getName);



	}
	public static void main(String[] args) {
		System.out.println("123");

		List<Integer> nums = new ArrayList();
		nums.add(1);
		nums.add(1);
		nums.add(null);
		nums.add(2);
		nums.add(3);
		nums.add(4);
		nums.add(null);
		nums.add(5);
		nums.add(6);
		System.out.println("求和："+nums
				.stream()//转成Stream
				.filter(team -> team!=null)//过滤
				.distinct()//去重
				.mapToInt(num->num*2)//map操作
				.skip(2)//跳过前2个元素
				.limit(4)//限制取前4个元素
				.peek(System.out::println)//流式处理对象函数
				.sum());//

	}
}

/**
 *
 *  lambda 表达式依赖于“函数式接口”，即：仅仅只包含一个抽象方法的接口。
 *
 *每一个该类型的lambda表达式都会被匹配到这个抽象方法。因为 默认方法 不算抽象方法，所以你也可以给你的函数式接口添加默认方法。
 *
 * @param <F>
 * @param <T>
 */
@FunctionalInterface
interface Converter<F, T> {
	T convert(F from);

	//这个方法可以加，因为默认方法不算抽象方法
	default void say(){
		System.out.println("shuo .........");
	}

	//有了上面的注解，加上这个抽象方法，就报错了。
	//public void getName();
}

class Person{

	public static void say(){
		System.out.println("111111");
	}

	private String name;

	public Person() {
	}

	public Person(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}